En spring podemos usar las funciones nativas de spring para hacer consultas, pero a mayores podemos usar consultas JPQL y consultas nativas de SQL.
Consulta JPQL:
@Query("SELECT s FROM Skill s ORDER BY s.id DESC")
List<Skill> findAllByOrderBySkillAsc();
Consulta nativa:
@Query(
value="SELECT skill FROM skills",
nativeQuery=true
)
List<String> allSkills();
La principal diferencia entre las dos consultas es que una gestiona objetos (la JPQL) y la otra gestiona tablas de la base de datos (la nativa)
En el caso de la consulta JPQL la parte despues del FROM hace referencia a los objetos que tenemos definidos en el modelo, de manera que en este caso Skill hace referencía a la clase Skill y tenemos que escribirlo tal y como está la clase.
Otra cosa a tener en cuenta de las consultas JPQL es que la parte del select (lo que devuelve la consulta) tiene que ser exactamente el objeto que indicamos en la funcion que está asociada a dicha consulta:
En nuestro caso es un objeto de tipo Skill como la consulta puede devolver mas de un resultado pues es una lista de Skill List<Skill>
Otra cosa a tener en cuenta con JPQL es que como manipulamos objetos, podemos tambien acceder a sus atributos, de igual manera que dentro de un lenguaje, pero dentro de las consultas.
Si por ejemplo tenemos un objeto vehiculo que a su vez contiene un objeto coche con un atributo puerta, podemos acceder en la consulta usando vehiculo.coche.puerta, esto da mucho juego en las tablas que se originan como resultado de cruzar dos tablas, ya que nos da acceso a objetos con mucha información relacionada, en el proyecto de la academy es el ejemplo de MemberSkill, usando ese objeto podemos acceder tanto a members como skills y la información relacionada entre ellos.
En principio en las consultas JPQL solo podemos devolver objetos que están en el modelo de datos ya que son los que podemos consultar (si intentamos devolver columnas separadas que coincidan con los atributos de un objeto no funcionará siempre tenemos que devolver un objeto completo), pero existe una manera en la que podemos generar un nuevo objeto en la propia consulta y devolverlo en la funcion
Para poder devolver un objeto personalizado un ejemplo sería el siguiente:
@Query("SELECT new main.dto.StatisticData(ms.skill.skill, COUNT(s.skill)) FROM Skill s LEFT JOIN MemberSkill ms ON ms.skill.id = s.id GROUP BY s.skill")
List<StatisticData> findMembersForEachSkill();
En la parte del SELECT tenemos que poner una sentencia new() indicando el objeto que queremos crear y los argumentos del constructor, para realizar esto obviamente tenemos que tener un constructor adecuado en dicho objeto
De esta manera podemos asociar un objeto que no está en el modelo de datos a la salida de una consulta con JPQL.
Las consultas nativas son consultas SQL ejecutadas tal cual dentro del repositorio, la particularidad que tienen es que en el SELECT la cantidad de columnas tiene que coincidir con el numero de atributos del objeto, para que cada columna se asocie a un atributo concreto (tambien tienen que coincidir el tipo de datos)
Para utilizar una consulta nativa tenemos que indicar la opcion value en la etiqueta @Query y la opcion nativeQuery, tal que así:
@Query(
value="SELECT skill FROM skills",
nativeQuery=true
)
List<String> allSkills();
En este ejemplo simplemente estamos sacando una columna que es un string (skill), por lo tanto el objeto que tiene que devuelve la funcion es un String, como la consulta puede devolver varias filas pues el objeto es List<String>, si por ejemplo en el select tuviesemos dos campos uno string y otro int el objeto que devolviese la funcion asociada a la consulta tendría que tener dos atributos, uno string y otro int.
Otra cosa a tener en cuenta en las consultas nativas es que a diferencia de las consultas JPQL no estamos tratando con objetos, estamos tratando directamente con las tablas de la base de datos, por lo tanto tenemos que hacer referencia a las tablas tal cual estan definidas en la propia base de datos.
Spring | Repository | JPA | Consultas